﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufItem.h"
#include "GnufInfo.h"
#include "GnufMatrixButtonControl.h"
/// \file GnufMatrixButton.h

namespace gnuf {
    class QtMatrixButton;
    class ButtonEx;
    class ButtonAppearanceSetting;
    /// \brief 矩阵按钮
    class GNUF_BASE_EXPORT MatrixButton 
        : public ItemWith<QtMatrixButton>
        , public MatrixButtonControlAdaptation
    {
        CANNOT_COPY_OR_ASSIGN(MatrixButton);
        using Buttons = std::map<Point, gcmp::OwnerPtr<ButtonEx>>;
    public:
        static const EItemType Type;
        MatrixButton(Item* parent, EMatrixSize size = EMatrixSize::e2x2);
        ~MatrixButton();

        /// \brief 设置按钮矩阵的尺寸
        /// \details 目前支持的选项包括e2x2和e3x3
        /// \warn 默认构造的是e2x2的矩阵，如果需要改变，需要在构造对象后立即调用改方法，否则可能导致设置失败
        void setMatrixSize(EMatrixSize size);

        /// \brief 在指定位置添加按钮
        /// \details 如果添加按钮的位置超出当前矩阵的范围，则弹出调试警告。
        virtual void addButtonAt(Point p) override;

        /// \brief 在指定为值删除按钮
        /// \details 如果删除的按钮超出矩阵的范围，则弹出调试警号，删除后的按钮，图标同时删除，会以占位符的形式存在
        virtual void removeButtonAt(Point p) override;

        /// \brief 禁用指定位置的按钮
        /// \details 如果禁用的按钮超出矩阵的范围，则弹出调试警号，禁用后的按钮，保留图标，但是不可以交互
        virtual void disableButtonAt(Point p) override;

        /// \brief 禁用一组位置的按钮
        void disableButtonAt(const std::vector<Point>& buttons);

        /// \brief 使能指定位置的按钮
        /// \details 如果指定的位置超出当前矩阵的范围，则弹出调试警号，使能后的按钮，可以点击交互。
        virtual void enableButtonAt(Point p) override;

        void enableButtonAt(const std::vector<Point>& buttons);

        /// \brief 为一组按钮设置Info
        virtual void assignInfos(const std::map<Point, Info>&) override;

        void assignCaption(const std::map<Point, std::wstring>& captions);

        void assignIcon(const std::map<Point, std::wstring>& icons);

        /// \brief 设置当前选中的按钮
        virtual void setSelectedButton(Point p) override;

        /// \brief 获取当前选中的按钮
        Point selectedButton() const {return m_selectedButton; }

        EMatrixSize matrixSize() const { return m_size; }

        const Buttons& buttons() const { return m_buttons; }
        std::vector<std::pair<Point, ButtonEx*>> rawButtons() ;
    protected:
        // inherit from ItemWith
        virtual void onPostVisibilityChanged() override;
        virtual void onDisconnectFromMyQtItem() override;
        virtual void onPostInfoChanged() override;
        virtual void onPostAppearanceSettingChanged() override;
        virtual void onPostAbilityChanged() override;

        // inherit from MatrixButtonControlAdpatation...
        virtual void onAbilityChanged(bool) override;
        virtual void onCollectLocation(std::set<const gcmp::UniqueString*>& locations)const override;
        virtual void onConnectedWith(InputControl*) override;

    private:
        /// \brief 设置矩阵按钮的尺寸，即按钮的个数
        void initialButtons();
        inline int edgeLength() const { return static_cast<int>(m_size); }

    private:
        Buttons m_buttons;
        Point m_selectedButton{-1, -1};
        EMatrixSize m_size = EMatrixSize::e2x2;
    };
}
